package com.wlyuan.open.application.sms.service;

import com.alibaba.excel.util.StringUtils;
import com.wlyuan.captcha.client.CaptchaClient;
import com.wlyuan.core.exception.AssertUtils;
import com.wlyuan.core.exception.ValueError;
import com.wlyuan.open.application.sms.SmsCodeValidate;
import com.wlyuan.open.constants.SmsType;
import com.wlyuan.open.dto.OpenSmsCodeDTO;
import com.wlyuan.open.exception.CaptchaException;
import com.wlyuan.sms.code.SmsCodeClient;
import com.wlyuan.sms.utils.SmsResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author lijing
 */
@RequiredArgsConstructor
@Slf4j
@Service
public class SmsService {
    private final CaptchaClient captchaClient;
    @Resource(name = "registerSmsClient")
    private SmsCodeClient registerSmsCodeClient;
    @Resource(name = "unbindMobileSmsClient")
    private SmsCodeClient unbindMobileSmsClient;
    @Resource(name = "changeAppSecretSmsClient")
    private SmsCodeClient changeAppSecretSmsClient;
    @Resource(name = "bindSmsClient")
    private SmsCodeClient bindSmsClient;

    private final Map<SmsType, SmsCodeClient> smsClient = new ConcurrentHashMap<>();

    @PostConstruct
    public void initialize() {
        smsClient.put(SmsType.REGISTER, registerSmsCodeClient);
        smsClient.put(SmsType.UNBIND_MOBILE, unbindMobileSmsClient);
        smsClient.put(SmsType.CHANGE_APP_SECRET, changeAppSecretSmsClient);
        smsClient.put(SmsType.BIND, bindSmsClient);
    }

    private SmsCodeClient getSmsCodeClient(Integer type) {
        var codeClient = Optional.ofNullable(type)
                .map(SmsType::fromValue)
                .map(smsClient::get)
                .orElse(null);
        AssertUtils.assertNotNull(codeClient, new ValueError("短信类型不存在"));
        return codeClient;
    }

    public void send(OpenSmsCodeDTO sms) {
        logger.info("发送短信验证码: {}", sms);
        if (StringUtils.isBlank(sms.getMobile())) {
            throw new ValueError("手机号不能为空");
        }
        var codeClient = getSmsCodeClient(sms.getType());
        var result = codeClient.send(sms.getMobile(), sms.getRequestId(),
                sms.getCaptcha(), captchaClient::validate);
        smsResult(result);
    }

    private void smsResult(SmsResult smsResult) {
        if (!smsResult.success()) {
            throw new ValueError(smsResult.getMessage());
        }
    }

    public void validate(SmsCodeValidate smsCodeValidate) {
        logger.info("短信验证码验证: {}", smsCodeValidate);
        var codeClient = getSmsCodeClient(smsCodeValidate.getType());
        var validate = codeClient.validate(smsCodeValidate.getMobile(), smsCodeValidate.getCode());
        logger.info("短信验证码验证结果: {}", validate);
        if (!validate) {
            logger.error("短信验证码错误: {},{}", smsCodeValidate, codeClient);
            throw new CaptchaException("短信验证码错误");
        }
        codeClient.remove(smsCodeValidate.getMobile());
    }
}
